// -*-c#-*-
// License: New BSD License : http://www.opensource.org/licenses/bsd-license.php
//
// Copyright (c) 2008, Brothers In Arms/Burl Nyswonger
//
// See: BiaVote.uc for full License
// 
//@L

class BiaVoteMutator extends UTMutator
    Config( BiaVote );

`include( BiaVote/Classes/BiaStdInc.uci ) 
`include( BiaVote/Classes/BiaVote.uci )


// --------------------------------------------------------------------------

// Actor Removal
var bool                                bParsedConfig, bHaveRemoval, bFirstPlayer;
var array<string>                       aRemoveGroups;
var string                              BiaVoteGame;

var UTGame                              GameObject;
var string                              GameOptions;

// --------------------------------------------------------------------------


private function bool ParseConfig()
{
    local int GameIndex;
    local string sGroups;

    if( bParsedConfig )
    {
        return bHaveRemoval;  // after this, goto cleanup to return!
    }

    `BiaEnter();
    
    if( BiaVoteGame == "" )
    {
        BiaVoteGame = class'Engine.GameInfo'.static.ParseOption(GameOptions, "BiaVoteGame");
        if( BiaVoteGame == "" )
        {
            `BiaError("Unable to find Option=BiaVoteGame - check the docs for BiaVote, Version " $ `BiaVoteVersion);
            goto Cleanup;
        }
    }
    
    GameIndex = class'BiaVote.BiaVote'.default.Games.Find('Game', BiaVoteGame);
    if( GameIndex < 0 )
    {
        `BiaError("Unable to find Game="$BiaVoteGame$" in Games[]");
        goto Cleanup;
    }
    
    sGroups = class'BiaVote.BiaVote'.default.Games[GameIndex].RemoveItems;
    if( sGroups == "" )
    {
        goto Cleanup;
    }
    
    ParseStringIntoArray(sGroups, aRemoveGroups, ",", true);
    if( aRemoveGroups.Length > 0 )
    {
        `BiaDbg("Have removal groups");
        bHaveRemoval = true;
    }
    else
    {
        `BiaDbg("No removal groups");
    }
    
    Cleanup:
    bParsedConfig = true;
    `BiaExit();
    return bHaveRemoval;
}

//
// Since we destroy the UTGame.UTVoteCollector object, we must replace
// the reference that would have been set with our own collector.
private function GameEnding()
{
    local UTVoteCollector FVC;
    
    if( class'BiaVote.BiaVote'.static.IsRestarting() )
    {
        ClearTimer('GameEnding');
        return;
    }
    
    if(UTGame(WorldInfo.Game).VoteCollector == None ||
       UTGame(WorldInfo.Game).VoteCollector.IsA('BiaVoteFauxVoteCollector'))
    {
        FVC = class'BiaVote.BiaVote'.static.GetMyVoteCollector();
        if( FVC != None && FVC.IsA('BiaVoteFauxVoteCollector'))
        {
            `BiaDbg("Hacking game's VoteCollector object with: " $ FVC );
            UTGame(WorldInfo.Game).VoteCollector = FVC;
        }
    }
}

//
// This can't be called till after Engine.GameInfo::InitGame() has returned.
//
private function HackVoting()
{
    `BiaEnter();
    `BiaDbg("Hacking the voting - forcing to on");
    GameObject.bAllowMapVoting = true;
    GameObject.VoteDuration = 120;
    `BiaExit();
}

function bool CheckReplacement(Actor Other)
{
    local int i;
    local string sGroup, was;
    local bool res;


    //TODO: what is safe -- do I even care -- they set up their own .ini ...
    //      at least don't allow ourselve's, etc... -- check package name?
    //      if( Other.GetPackageName() != "UTGame" && Other.GetPackageName() != 'UTGameContent')
    //      {
    //          return;
    //      }
    // will that be good enouhg? - just the default game content? - or Info too?
    //
    if( Other.IsA('Info') )
    {
        if( Other.IsA('UTVoteCollector') && ! Other.IsA('BiaVoteFauxVoteCollector') )
        {
            `BiaDbg("Destroying this: " $ Other );
            class'BiaVote.BiaVote'.static.GameDoMapVote();
            SetTimer(1, true, 'GameEnding');
            return false;
        }
        // hmm.... Probably not such a good idea to kill Info classes we don't know about...
        return true;
    }

    if( ParseConfig() )
    {
        i = class'BiaVote.BiaVote'.default.Items.Find('Item', string(Other.Class));
        if(i > -1 )
        {
            sGroup = class'BiaVote.BiaVote'.default.Items[i].Group;
            if( sGroup != "" )
            {
                if( aRemoveGroups.Find( sGroup ) > -1 )
                {
                    `BiaLog("Removing Item in Group '" $ sGroup $ "' named: " $ Other );
                    was = string(Other.Class);
                    // give other muts a chance to override me...
                    res = Super.CheckReplacement(Other);
                    // If they replace it and want to keep it, thats fine...
                    if((string(Other.Class) != was) && res)
                    {
                        return true;
                    }
                    // ...Otherwise, I'm gonna destroy it.
                    return false;
                }
            }
        }
    }

    res = Super.CheckReplacement(Other);

/*    
    if( res && UTPawn(Other) != None )
    {
        // lol - what a blast -- Manta's scattered all over the place!
        // UTPawn(Other).HoverboardClass = class'UTGameContent.UTVehicle_Manta_Content';
    }
*/
    
    return res;
}


function Mutate(string MutateString, PlayerController Sender)
{
    `BiaDbg("Mutate '"$ MutateString $"' - from: " $ Sender );
    MutateString = Locs(MutateString);
    if( MutateString == "vote" || MutateString == "biavote" )
    {
        class'BiaVote.BiaVote'.static.ExecPlayerOpenUI( Sender );
    }
    Super.Mutate(MutateString, Sender);
}

//
// Deal with enabling/disabling the translocator or hoverboard.
// friggin-only-one can be active w/o a little hacking :-(
//
private function SetupMobilityOptions()
{
    local int HbTr;      // Bit#0 == Translocator, Bit#1 == Hoverboard
    local string InOpt;

    `BiaEnter();

    //TODO: need a mutator - need somehow to figure out how to get my
    // trans camera to work w/o doing my own PlayerController class...
    // Perhaps need an interaction to let you select between which
    // the mapped key will select when hit - selecting will swap one
    // for the other placing the non-ToggleTranslocator()-key associated
    // item into inventory (or an inventory wrapper in the case of HB)
    // May be able to do this with a custom inventory mgr as well - but
    // there are pitfalls...  Damn ToggleTranslocator()...
    
    HbTr = 0;
 
    // parse opt as a string first - otherwise, empty-string == bool(false)
    
    InOpt = class'Engine.GameInfo'.static.ParseOption(GameOptions, "EnableTranslocator");
    if( InOpt != "" )
    {
        HbTr = HbTr | (bool(InOpt) ? 0x01 : 0x00 );
        `BiaDbg("EnableTranslocator: " $ HbTr & 0x01);
    }
    InOpt = class'Engine.GameInfo'.static.ParseOption(GameOptions, "EnableHoverboard");
    if( InOpt != "" )
    {
        HbTr = HbTr | (bool(InOpt) ? 0x02 : 0x00 );
        `BiaDbg("EnableHoverboard: " $ HbTr & 0x02 );
    }
    
    `BiaDbg("Parsed Options - HbTr: " $ HbTr );

    // If either enabled - need to check for conflict...
    if( HbTr != 0 )
    {
        // paranoia
        `BiaAssert( HbTr == ( HbTr & 0x03 ) );
        
        // if both are enabled - let the GameType decide but favor Trans over Hover
        if( HbTr == 0x03 )
        {
            HbTr = HbTr & (GameObject.bAllowTranslocator ?      0x01 :
                           GameObject.bAllowHoverboard ? 0x02 : 0x01   );
            
            `BiaDbg("Conflict - both trans/hover are enabled, chose: " $ HbTr);
        }
        GameObject.bAllowTranslocator = ((HbTr & 0x01) == 0x01 ? true : false);
        GameObject.bAllowHoverboard   = ((HbTr & 0x02) == 0x02 ? true : false);
    }
    
    if( GameObject.bAllowTranslocator )
    {
        InOpt = class'Engine.GameInfo'.static.ParseOption(GameOptions, "TranslocatorClass");
        if(InOpt != "")
        {
            GameObject.TranslocatorClass = class<UTWeapon>(DynamicLoadObject(InOpt, class'Class'));
            if( GameObject.TranslocatorClass == None )
            {
                `BiaError("Failed to load TranslocatorClass: " $ InOpt);
            }
        }
        if( GameObject.TranslocatorClass == None )
        {
            GameObject.TranslocatorClass  = class'UTGameContent.UTWeap_Translocator_Content';
        }
    }
    
    `BiaExit();
}


function InitMutator(string Options, out string ErrorMessage)
{
    
    `BiaDbg("InitMutator()...");

    `ifDebug( class'BiaVote.BiaVote'.static.ReportWorldObjects(WorldInfo) );

    // The order of things is kind of important - NOTE: we must be the
    //  very first Mutator on the command line - very imporant, verry important!
    //
    //  First: Spawn our BiaVote singleton!!!
    //
    if( class'BiaVote.BiaVote'.static.SpawnInstance( WorldInfo.Game ) )
    {
        //Issue:6
        SetTimer(6.0, false, 'HackVoting');
    }
    else
    {
        `BiaError("UNABLE TO CREATE BiaVote.BiaVote singleton!");
    }


    // things about to be called need these to be set:
    GameOptions = Options;
    GameObject  = UTGame(WorldInfo.Game);


    //
    // Second: We need to parse our config right away!
    //
    ParseConfig();

    //
    // Third: set up our mobility options - other muts may revert these,
    // and that's just the way it is, I guess...
    //
    SetupMobilityOptions();
    
    Super.InitMutator(GameOptions, ErrorMessage);
    
    GotoState('Bar');
}



function NotifyLogout(Controller Exiting)
{
    class'BiaVote.BiaVote'.static.NotifyLogout( Exiting );
    Super.NotifyLogout( Exiting );
}

function NotifyLogin(Controller NewPlayer)
{
    if( !bFirstPlayer )
    {
        bFirstPlayer = true;
        HackVoting();
    }
    Super.NotifyLogin( NewPlayer );
    class'BiaVote.BiaVote'.static.NotifyLogin( NewPlayer );
}

defaultproperties
{
    bParsedConfig = false;
    bHaveRemoval = false;
    bFirstPlayer = false;
    bExportMenuData=false
}
